package com.logic.modular.game.core.domain;

import com.comment.exception.ServiceException;
import com.logic.comment.util.RedisUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;

@SuppressWarnings("unchecked")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MatchPool {
    private int mapId;
    private int type;
    private int startThreshold;
    public Set<Long> playerIds;

    private static final String MATCH_POOL_KEY1 = "matchPool";
    public static final String MATCH_POOL_KEY2 = "%d-%d-%d";
    private static final String PLAYER_MATCH_POOL_INFO_KEY = "player:%d:logMatchPool";

    /**
     * 加入并获取匹配池
     */
    public static void joinMatchPool(
            Long playerId,
            Long mapId,
            Integer type,
            Integer startThreshold
    ) {
        String key1 = MATCH_POOL_KEY1;
        String key2 = String.format(MATCH_POOL_KEY2, mapId, type, startThreshold);
        MatchPool matchPool = (MatchPool) RedisUtils.redisUtils().hGet(key1, key2);
        if (matchPool == null) {
            matchPool = new MatchPool();
            matchPool.setMapId(mapId.intValue());
            matchPool.setType(type);
            matchPool.setStartThreshold(startThreshold);
            matchPool.setPlayerIds(new HashSet<>());
        }
        if (matchPool.playerIds.contains(playerId)) {
            return;
        }

        matchPool.playerIds.add(playerId);
        RedisUtils.redisUtils().hPut(key1, key2, matchPool);
        logPlayerMatchInfo(playerId, mapId, type, startThreshold);
    }

    public static void logPlayerMatchInfo(
            Long playerId,
            Long mapId,
            Integer type,
            Integer startThreshold
    ) {
        String key1 = String.format(PLAYER_MATCH_POOL_INFO_KEY, playerId);
        String key2 = String.format(MATCH_POOL_KEY2, mapId, type, startThreshold);
        RedisUtils.redisUtils().set(key1, key2);
    }

    public static String obtainPlayerMatchInfo(
            Long playerId
    ) {
        String key1 = String.format(PLAYER_MATCH_POOL_INFO_KEY, playerId);
        return (String) RedisUtils.redisUtils().get(key1);
    }

    /**
     * 尝试开始
     */
    public static Set<Long> tryStarMatch(
            Long mapId,
            Integer type,
            Integer startThreshold
    ) {
        String key1 = MATCH_POOL_KEY1;
        String key2 = String.format(MATCH_POOL_KEY2, mapId, type, startThreshold);
        MatchPool matchPool = (MatchPool) RedisUtils.redisUtils().hGet(key1, key2);

        if (matchPool.playerIds.size() < startThreshold) {
            return null;
        }

        // 创建一个新的 Set 来存储移除的元素
        Set<Long> removedElements = new HashSet<>();

        // 移除count个元素到新的 Set 中
        for (Iterator<Long> iterator = matchPool.playerIds.iterator(); iterator.hasNext() && removedElements.size() < startThreshold; ) {
            Long element = iterator.next();
            iterator.remove();
            removedElements.add(element);
        }
        RedisUtils.redisUtils().hPut(key1, key2, matchPool);
        // 移除玩家匹配池记录
        for (Long playerId : matchPool.playerIds) {
            String key = String.format(PLAYER_MATCH_POOL_INFO_KEY, playerId);
            RedisUtils.redisUtils().delete(key);
        }

        return removedElements;
    }

    public static boolean leftMatchPool(
            Long playerId
    ) {
        String key1 = MATCH_POOL_KEY1;
        String key2 = obtainPlayerMatchInfo(playerId);
        if (key2 == null){
            throw new ServiceException("该玩家不在匹配中");
        }
        MatchPool matchPool = (MatchPool) RedisUtils.redisUtils().hGet(key1, key2);
        if (matchPool.playerIds.contains(playerId)) {
            matchPool.playerIds.remove(playerId);
            RedisUtils.redisUtils().hPut(key1, key2, matchPool);
            return true;
        } else {
            return false;
        }
    }
}
